package com.jichangxiu.framework.utils;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.jichangxiu.common.annotation.Job;
import com.jichangxiu.common.annotation.Power;
import com.jichangxiu.common.annotation.Role;
import com.jichangxiu.common.constant.Constants;
import com.jichangxiu.common.enums.Logical;
import com.jichangxiu.common.utils.ServletUtils;
import com.jichangxiu.framework.entity.bo.SecurityUser;
import org.springframework.security.core.GrantedAuthority;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;

public class AuthUtils {

    public static void checkLogin() {
        if (!hasNoAuthUrl() && ObjectUtil.isNull(SecurityUtils.getUserInfo()))
            throw new RuntimeException("【AuthUtils】该资源只有登录用户能够访问，请先登录系统");
    }

    public static void checkJob(Job job) {
        if (job.logical() == Logical.AND)
            checkJobAnd(job.value());
        else
            checkJobOr(job.value());
    }

    public static void checkJobAnd(String... posts) {
        for (String post : posts)
            if (!hasPost(post))
                throw new RuntimeException("【AuthUtils】该资源只有同时具备【" + ArrayUtil.join(posts, ",") + "】岗位能够访问");
    }

    public static void checkJobOr(String... posts) {
        boolean flag = false;
        for (String post : posts)
            if (hasPost(post)) {
                flag = true;
                break;
            }
        if (!flag)
            throw new RuntimeException("【AuthUtils】该资源只有具备任意【" + ArrayUtil.join(posts, ",") + "】岗位能够访问");
    }

    public static boolean hasPost(String post) {
        if (StrUtil.isEmpty(post))
            return true;
        if (hasNoAuthUrl())
            return true;
        SecurityUser securityUser = SecurityUtils.getUserInfo();
        if (ObjectUtil.isNull(securityUser) || ObjectUtil.isEmpty(securityUser.getSecurityPostList()))
            return false;
        return hasPermission(securityUser.getSecurityPostList(), post);
    }

    public static void checkRole(Role role) {
        if (role.logical() == Logical.AND)
            checkRoleAnd(role.value());
        else
            checkRoleOr(role.value());
    }

    public static void checkRoleAnd(String... roles) {
        for (String role : roles)
            if (!hasRole(role))
                throw new RuntimeException("【AuthUtils】该资源只有同时具备【" + ArrayUtil.join(roles, ",") + "】角色能够访问");
    }

    public static void checkRoleOr(String... roles) {
        boolean flag = false;
        for (String role : roles)
            if (hasRole(role)) {
                flag = true;
                break;
            }
        if (!flag)
            throw new RuntimeException("【AuthUtils】该资源只有具备任意【" + ArrayUtil.join(roles, ",") + "】角色能够访问");
    }

    public static boolean hasRole(String role) {
        if (StrUtil.isEmpty(role))
            return true;
        if (hasNoAuthUrl())
            return true;
        SecurityUser securityUser = SecurityUtils.getUserInfo();
        if (ObjectUtil.isNull(securityUser) || ObjectUtil.isEmpty(securityUser.getSecurityRoleList()))
            return false;
        return hasPermission(securityUser.getSecurityRoleList(), role);
    }

    public static void checkPower(Power power) {
        if (power.logical() == Logical.AND)
            checkPowerAnd(power.value());
        else
            checkPowerOr(power.value());
    }

    public static void checkPowerAnd(String... powers) {
        for (String power : powers)
            if (!hasPower(power))
                throw new RuntimeException("【AuthUtils】该资源只有同时具备【" + ArrayUtil.join(powers, ",") + "】权限能够访问");
    }

    public static void checkPowerOr(String... powers) {
        boolean flag = false;
        for (String power : powers)
            if (hasPower(power)) {
                flag = true;
                break;
            }
        if (!flag)
            throw new RuntimeException("【AuthUtils】该资源只有具备任意【" + ArrayUtil.join(powers, ",") + "】角色能够访问");
    }

    public static boolean hasPower(String power) {
        if (StrUtil.isEmpty(power))
            return true;
        if (hasNoAuthUrl())
            return true;
        SecurityUser securityUser = SecurityUtils.getUserInfo();
        if (ObjectUtil.isNull(securityUser) || ObjectUtil.isEmpty(securityUser.getSecurityPowerList()))
            return false;
        return hasPermission(securityUser.getSecurityPowerList(), power);
    }

    public static boolean hasPermission(Collection<? extends GrantedAuthority> authorities, String permission) {
        if (hasNoAuthUrl())
            return true;
        if (hasAllPermission(authorities))
            return true;
        boolean status = false;
        for (GrantedAuthority authority : authorities) {
            status = authority.getAuthority().equals(StrUtil.trim(permission));
            if (status)
                break;
        }
        return status;
    }

    public static boolean hasAllPermission(Collection<? extends GrantedAuthority> authorities) {
        if (hasNoAuthUrl())
            return true;
        boolean flag = false;
        for (GrantedAuthority authority : authorities) {
            flag = authority.getAuthority().equals(Constants.ALL_PERMISSION);
            if (flag)
                break;
        }
        return flag;
    }

    public static boolean hasNoAuthUrl() {
        HttpServletRequest httpServletRequest = ServletUtils.getRequest();
        if (ObjectUtil.isNotNull(httpServletRequest))
            return ArrayUtil.contains(Constants.JCX_PROPERTIES.getSecurityProperties().getNoAuthPath().split(","), httpServletRequest.getRequestURI());
        return false;
    }

}
